package com.zmn.plat.business.impl.product;

import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.zmn.common.utils.number.NumberUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zmn.common.dictionary.DictModel;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.mcc.cas.model.LoginStaff;
import com.zmn.plat.business.interfaces.product.BaseCityPriceRatioBService;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.common.dictionary.BaseCityRatioTypeEnum;
import com.zmn.plat.common.dictionary.ProductDict;
import com.zmn.plat.model.entity.area.BaseArea;
import com.zmn.plat.model.entity.base.city.ratio.BaseCityRatio;
import com.zmn.plat.model.entity.base.city.ratio.BaseCityRatioQuery;
import com.zmn.plat.model.entity.product.CityCategRatioQuery;
import com.zmn.plat.model.vo.area.ProvinceCityVO;
import com.zmn.plat.model.vo.product.BaseCityCategoryRatioModifyVo;
import com.zmn.plat.model.vo.product.cityRatio.CityRatioBatchVO;
import com.zmn.plat.services.interfaces.area.BaseAreaService;
import com.zmn.plat.services.interfaces.base.city.ratio.BaseCityRatioService;

/**
 * @author linfeng
 * @since 2019/08/23/15:05
 */
@Service
public class BaseCityPriceRatioBServiceImpl implements BaseCityPriceRatioBService {
    private Logger logger = LoggerFactory.getLogger(BaseCityPriceRatioBServiceImpl.class);

    @Resource
    BaseCityRatioService baseCityRatioService;

    @Resource
    BaseAreaService baseAreaService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SuppressWarnings("Duplicates")
    public void addEditCategoryRatio(String mcStaffName, BaseCityCategoryRatioModifyVo baseCityCategoryRatioModifyVo) {
        Date now = DateUtil.getNow();
        Integer cityId = baseCityCategoryRatioModifyVo.getCategOneRatio().getCityId();
        Integer bizType = baseCityCategoryRatioModifyVo.getCategOneRatio().getBizType();
        Integer priceType = baseCityCategoryRatioModifyVo.getCategOneRatio().getPriceType();
        Integer servCategId = baseCityCategoryRatioModifyVo.getCategOneRatio().getServCategId();
        Integer categOneId = baseCityCategoryRatioModifyVo.getCategOneRatio().getCategOneId();
        BaseCityRatio categOneRatioResult =
                baseCityRatioService.findByRatioTypeAndCityAndCategAndBizType(priceType, BaseCityRatioTypeEnum.CITYCATEGONERATIO.getCode(), cityId, servCategId, categOneId, null, bizType);
        Double categOneRatio = baseCityCategoryRatioModifyVo.getCategOneRatio().getToBeEffectiveRatio();

        if (categOneRatioResult == null) {
            if (categOneRatio != null) {
                BaseCityRatio createOneRatio = new BaseCityRatio();
                createOneRatio = baseCityCategoryRatioModifyVo.getCategOneRatio();
                createOneRatio.setCreater(mcStaffName);
                createOneRatio.setUpdater(mcStaffName);
                createOneRatio.setCreateTime(now);
                createOneRatio.setUpdateTime(now);
                createOneRatio.setRatioType(BaseCityRatioTypeEnum.CITYCATEGONERATIO.getCode());
                baseCityRatioService.insert(createOneRatio);
            }
        } else {
            if (categOneRatioResult.getRatio() == null && categOneRatio == null) {
                baseCityRatioService.deleteByKey(categOneRatioResult.getRatioId());
            } else {
                categOneRatioResult.setToBeEffectiveRatio(categOneRatio);
                categOneRatioResult.setUpdateTime(DateUtil.getNow());
                categOneRatioResult.setUpdater(mcStaffName);
                categOneRatioResult.setEffectiveDate(baseCityCategoryRatioModifyVo.getCategOneRatio().getEffectiveDate());
                baseCityRatioService.updateByKey(categOneRatioResult);
            }
        }

        BaseCityRatioQuery baseCityRatioQuery = new BaseCityRatioQuery();
        baseCityRatioQuery.setPriceType(priceType);
        baseCityRatioQuery.setBizType(bizType);
        baseCityRatioQuery.setRatioType(BaseCityRatioTypeEnum.CITYCATEGTWORATIO.getCode());
        baseCityRatioQuery.setCityId(cityId);
        baseCityRatioQuery.setServCategId(servCategId);
        baseCityRatioQuery.setCategOneId(categOneId);
        List<BaseCityRatio> dbCategTwoRatios = baseCityRatioService.listByQuery(baseCityRatioQuery);
        CityCategRatioQuery cityCategRatioQuery = new CityCategRatioQuery();
        BeanUtils.copyProperties(baseCityRatioQuery, cityCategRatioQuery);

        List<BaseCityRatio> categTwoRatios = baseCityCategoryRatioModifyVo.getCategTwoRatioList();
        List<BaseCityRatio> insertRatioList = new ArrayList<>();
        List<Integer> deleteRatioList = new ArrayList<>();
        List<BaseCityRatio> updateRatioList = new ArrayList<>();
        if (categTwoRatios != null && categTwoRatios.size() > 0) {
            categTwoRatios.forEach(e -> {
                cityCategRatioQuery.setCategId(e.getCategId());
                BaseCityRatio dbRatio = findBaseCityRatioByQueryOfCategTwoRatioList(cityCategRatioQuery, dbCategTwoRatios);

                if (dbRatio == null) {
                    if (e.getToBeEffectiveRatio() != null) {
                        e.setRatioType(BaseCityRatioTypeEnum.CITYCATEGTWORATIO.getCode());
                        e.setCreater(mcStaffName);
                        e.setUpdater(mcStaffName);
                        e.setCreateTime(now);
                        e.setUpdateTime(now);
                        insertRatioList.add(e);
                    }
                } else {
                    if (dbRatio.getRatio() == null && e.getToBeEffectiveRatio() == null) {
                        deleteRatioList.add(dbRatio.getRatioId());
                    } else {
                        e.setUpdateTime(DateUtil.getNow());
                        e.setUpdater(mcStaffName);
                        e.setRatioId(dbRatio.getRatioId());
                        updateRatioList.add(e);
                    }
                }
            });

            if (CollectionUtil.isNotNullOrEmpty(insertRatioList)) {
                baseCityRatioService.insertBatch(insertRatioList);
            }
            if (CollectionUtil.isNotNullOrEmpty(deleteRatioList)) {
                baseCityRatioService.deleteByKeys(deleteRatioList);
            }
            if (CollectionUtil.isNotNullOrEmpty(updateRatioList)) {
                baseCityRatioService.updateToBeEffectiveRatioBatch(updateRatioList);
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SuppressWarnings("Duplicates")
    public void saveCityRatioBatch(LoginStaff mcStaff, CityRatioBatchVO cityRatioBatchVO) {
        List<ProvinceCityVO> provinceCityVOS = cityRatioBatchVO.getProvinceCityVOS();

        List<Integer> cityIdList = provinceCityVOS.stream().map(ProvinceCityVO::getCityId).collect(Collectors.toList());
        BaseCityRatioQuery baseCityRatioQuery = new BaseCityRatioQuery();
        baseCityRatioQuery.setCityIds(cityIdList);
        baseCityRatioQuery.setPriceType(cityRatioBatchVO.getPriceType());

        List<BaseCityRatio> updateRatioList = new ArrayList<>();
        List<BaseCityRatio> insertRatioList = new ArrayList<>();
        // 需要删除的系数集合
        List<Integer> deleteRatioList = new ArrayList<>();

        Date effectiveDate = cityRatioBatchVO.getEffectiveDate();
        if (NumberUtil.isNotNullOrZero(cityRatioBatchVO.getOutToBeEffectiveRatio())) {
            Double outToBeEffectiveRatio = cityRatioBatchVO.getOutToBeEffectiveRatio();
            addEditRatio(ProductConsts.BIZ_TYPE_C, cityRatioBatchVO, outToBeEffectiveRatio, provinceCityVOS, baseCityRatioQuery, updateRatioList, insertRatioList, deleteRatioList, effectiveDate, mcStaff);
        }
        if (NumberUtil.isNotNullOrZero(cityRatioBatchVO.getInToBeEffectiveRatio())) {
            Double inToBeEffectiveRatio = cityRatioBatchVO.getInToBeEffectiveRatio();
            addEditRatio(ProductConsts.BIZ_TYPE_F, cityRatioBatchVO, inToBeEffectiveRatio, provinceCityVOS, baseCityRatioQuery, updateRatioList, insertRatioList, deleteRatioList, effectiveDate, mcStaff);
        }
        if (NumberUtil.isNotNullOrZero(cityRatioBatchVO.getProjectToBeEffectiveRatio())) {
            Double projectToBeEffectiveRatio = cityRatioBatchVO.getProjectToBeEffectiveRatio();
            addEditRatio(ProductConsts.BIZ_TYPE_B, cityRatioBatchVO, projectToBeEffectiveRatio, provinceCityVOS, baseCityRatioQuery, updateRatioList, insertRatioList, deleteRatioList, effectiveDate, mcStaff);
        }
        if (NumberUtil.isNotNullOrZero(cityRatioBatchVO.getMeterToBeEffectiveRatio())) {
            Double meterToBeEffectiveRatio = cityRatioBatchVO.getMeterToBeEffectiveRatio();
            addEditRatio(null, cityRatioBatchVO, meterToBeEffectiveRatio, provinceCityVOS, baseCityRatioQuery, updateRatioList, insertRatioList, deleteRatioList, effectiveDate, mcStaff);
        }
        if (CollectionUtil.isNotNullOrEmpty(insertRatioList)) {
            baseCityRatioService.insertBatch(insertRatioList);
        }
        if (CollectionUtil.isNotNullOrEmpty(deleteRatioList)) {
            baseCityRatioService.deleteByKeys(deleteRatioList);
        }
        if (CollectionUtil.isNotNullOrEmpty(updateRatioList)) {
            baseCityRatioService.updateToBeEffectiveRatioBatch(updateRatioList);
        }

    }

    private void addEditRatio(Integer bizType,
                              CityRatioBatchVO cityRatioBatchVO,
                              Double toBeEffectiveRatio, List<ProvinceCityVO> provinceCities,
                              BaseCityRatioQuery baseCityRatioQuery,
                              List<BaseCityRatio> updateRatioList,
                              List<BaseCityRatio> insertRatioList,
                              List<Integer> deleteRatioList,
                              Date effectiveDate,
                              LoginStaff mcStaff) {
        baseCityRatioQuery.setBizType(bizType);
        if (Objects.isNull(bizType)) {
            baseCityRatioQuery.setRatioType(BaseCityRatioTypeEnum.CITYMETER3RATIO.getCode());
        }else{
            baseCityRatioQuery.setRatioType(BaseCityRatioTypeEnum.CITYRATIO.getCode());
        }
        List<BaseCityRatio> dbBaseCityRatios = baseCityRatioService.listByQuery(baseCityRatioQuery);

        Map<Integer, BaseCityRatio> map = dbBaseCityRatios.stream().collect(Collectors.toMap(BaseCityRatio::getCityId, o -> o));
        ProvinceCityVO provinceCityVO;
        for (int j = 0; j < provinceCities.size(); j++) {
            provinceCityVO = provinceCities.get(j);
            BaseCityRatio innerRatio = map.get(provinceCityVO.getCityId());
            if (Objects.isNull(innerRatio)) {
                if (toBeEffectiveRatio != null) {
                    BaseCityRatio baseCityRatio = new BaseCityRatio();
                    baseCityRatio.setProvinceId(provinceCityVO.getProvinceId());
                    baseCityRatio.setCityId(provinceCityVO.getCityId());
                    baseCityRatio.setBizType(bizType);
                    baseCityRatio.setPriceType(cityRatioBatchVO.getPriceType());
                    if (Objects.isNull(bizType)) {
                        baseCityRatio.setRatioType(BaseCityRatioTypeEnum.CITYMETER3RATIO.getCode());
                    }else{
                        baseCityRatio.setRatioType(BaseCityRatioTypeEnum.CITYRATIO.getCode());

                    }
                    baseCityRatio.setToBeEffectiveRatio(toBeEffectiveRatio);
                    baseCityRatio.setEffectiveDate(effectiveDate);
                    baseCityRatio.setUpdater(mcStaff.getRealName());
                    baseCityRatio.setUpdateTime(DateUtil.getNow());
                    baseCityRatio.setCreater(mcStaff.getRealName());
                    baseCityRatio.setCreateTime(DateUtil.getNow());
                    insertRatioList.add(baseCityRatio);
                }
            } else {
                if (innerRatio.getRatio() == null && toBeEffectiveRatio == null) {
                    deleteRatioList.add(innerRatio.getRatioId());
                } else {
                    innerRatio.setUpdateTime(DateUtil.getNow());
                    innerRatio.setUpdater(mcStaff.getRealName());
                    innerRatio.setToBeEffectiveRatio(toBeEffectiveRatio);
                    innerRatio.setEffectiveDate(effectiveDate);
                    updateRatioList.add(innerRatio);
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SuppressWarnings("Duplicates")
    public void saveCityCategRatioBatch(LoginStaff mcStaff, CityRatioBatchVO cityRatioBatchVO) {
        List<Integer> cityIdList = StringUtil.convertStrsToList(cityRatioBatchVO.getCityIdStr());

        Map<Integer, Integer> cityProvMap = new HashMap<>(cityIdList.size());
        if (CollectionUtil.isNotNullOrEmpty(cityIdList)) {
            List<BaseArea> cityList = baseAreaService.findByKeys(cityIdList);
            cityProvMap = cityList.stream().collect(Collectors.toMap(BaseArea::getAreaId, BaseArea::getParentId));
        }

        // 处理一级分类系数
        BaseCityRatioQuery baseCityRatioQuery = new BaseCityRatioQuery();
        baseCityRatioQuery.setCityIds(cityIdList);
        baseCityRatioQuery.setRatioType(BaseCityRatioTypeEnum.CITYCATEGONERATIO.getCode());
        baseCityRatioQuery.setServCategId(cityRatioBatchVO.getServCategId());
        baseCityRatioQuery.setCategOneId(cityRatioBatchVO.getCategOneId());
        baseCityRatioQuery.setBizType(cityRatioBatchVO.getBizType());
        baseCityRatioQuery.setPriceType(cityRatioBatchVO.getPriceType());
        List<BaseCityRatio> dbBaseCityCategOneRatios = baseCityRatioService.listByQuery(baseCityRatioQuery);

        List<BaseCityRatio> updateRatioList = new ArrayList<>();
        List<BaseCityRatio> insertRatioList = new ArrayList<>();
        // 需要删除的系数集合
        List<Integer> deleteRatioList = new ArrayList<>();

        Date effectiveDate = cityRatioBatchVO.getEffectiveDate();

        for (int i = 0; i < cityIdList.size(); i++) {
            Integer cityId = cityIdList.get(i);
            CityCategRatioQuery cityCategOneRatioQuery = new CityCategRatioQuery();
            cityCategOneRatioQuery.setCityId(cityId);
            cityCategOneRatioQuery.setRatioType(BaseCityRatioTypeEnum.CITYCATEGONERATIO.getCode());
            cityCategOneRatioQuery.setServCategId(cityRatioBatchVO.getServCategId());
            cityCategOneRatioQuery.setCategOneId(cityRatioBatchVO.getCategOneId());
            cityCategOneRatioQuery.setBizType(cityRatioBatchVO.getBizType());
            cityCategOneRatioQuery.setPriceType(cityRatioBatchVO.getPriceType());
            BaseCityRatio innerRatio = this.findBaseCityRatioByQueryOfCategOneRatioList(cityCategOneRatioQuery, dbBaseCityCategOneRatios);
            Double toBeEffectiveRatio = cityRatioBatchVO.getCategOneRatio().getToBeEffectiveRatio();
            if (Objects.isNull(innerRatio)) {
                if (toBeEffectiveRatio != null) {
                    BaseCityRatio baseCityRatio = new BaseCityRatio();
                    baseCityRatio.setProvinceId(cityProvMap.get(cityId));
                    baseCityRatio.setCityId(cityId);
                    baseCityRatio.setBizType(cityRatioBatchVO.getBizType());
                    baseCityRatio.setPriceType(cityRatioBatchVO.getPriceType());
                    baseCityRatio.setServCategId(cityRatioBatchVO.getServCategId());
                    baseCityRatio.setCategOneId(cityRatioBatchVO.getCategOneId());
                    baseCityRatio.setRatioType(BaseCityRatioTypeEnum.CITYCATEGONERATIO.getCode());
                    baseCityRatio.setToBeEffectiveRatio(toBeEffectiveRatio);
                    baseCityRatio.setEffectiveDate(effectiveDate);
                    baseCityRatio.setUpdater(mcStaff.getRealName());
                    baseCityRatio.setUpdateTime(DateUtil.getNow());
                    baseCityRatio.setCreater(mcStaff.getRealName());
                    baseCityRatio.setCreateTime(DateUtil.getNow());
                    insertRatioList.add(baseCityRatio);
                }
            } else {
                if (innerRatio.getRatio() == null && toBeEffectiveRatio == null) {
                    deleteRatioList.add(innerRatio.getRatioId());
                } else {
                    innerRatio.setUpdateTime(DateUtil.getNow());
                    innerRatio.setUpdater(mcStaff.getRealName());
                    innerRatio.setToBeEffectiveRatio(toBeEffectiveRatio);
                    innerRatio.setEffectiveDate(effectiveDate);
                    updateRatioList.add(innerRatio);
                }
            }
        }

        List<BaseCityRatio> categTwoRatioList = cityRatioBatchVO.getBaseCityRatioList();
        List<Integer> categIdList = categTwoRatioList.stream().map(e -> e.getCategId()).collect(Collectors.toList());
        baseCityRatioQuery.setRatioType(BaseCityRatioTypeEnum.CITYCATEGTWORATIO.getCode());
        baseCityRatioQuery.setCategIds(categIdList);
        List<BaseCityRatio> dbBaseCityCategTwoRatios = baseCityRatioService.listByQuery(baseCityRatioQuery);
        if (categTwoRatioList != null && categTwoRatioList.size() > 0) {
            for (int i = 0; i < cityIdList.size(); i++) {
                Integer cityId = cityIdList.get(i);
                for (BaseCityRatio e : categTwoRatioList) {
                    CityCategRatioQuery cityCategTwoRatioQuery = new CityCategRatioQuery();
                    cityCategTwoRatioQuery.setCityId(cityId);
                    cityCategTwoRatioQuery.setRatioType(BaseCityRatioTypeEnum.CITYCATEGTWORATIO.getCode());
                    cityCategTwoRatioQuery.setServCategId(cityRatioBatchVO.getServCategId());
                    cityCategTwoRatioQuery.setCategOneId(cityRatioBatchVO.getCategOneId());
                    cityCategTwoRatioQuery.setCategId(e.getCategId());
                    cityCategTwoRatioQuery.setBizType(cityRatioBatchVO.getBizType());
                    cityCategTwoRatioQuery.setPriceType(cityRatioBatchVO.getPriceType());
                    BaseCityRatio dbRatio = findBaseCityRatioByQueryOfCategTwoRatioList(cityCategTwoRatioQuery, dbBaseCityCategTwoRatios);

                    if (dbRatio == null) {
                        if (e.getToBeEffectiveRatio() != null) {
                            BaseCityRatio insertRatio = new BaseCityRatio();
                            BeanUtils.copyProperties(e, insertRatio);
                            insertRatio.setCityId(cityId);
                            insertRatio.setProvinceId(cityProvMap.get(cityId));
                            insertRatio.setRatioType(BaseCityRatioTypeEnum.CITYCATEGTWORATIO.getCode());
                            insertRatio.setPriceType(cityRatioBatchVO.getPriceType());
                            insertRatio.setBizType(cityRatioBatchVO.getBizType());
                            insertRatio.setCreater(mcStaff.getRealName());
                            insertRatio.setEffectiveDate(effectiveDate);
                            insertRatio.setUpdater(mcStaff.getRealName());
                            insertRatio.setCreateTime(DateUtil.getNow());
                            insertRatio.setUpdateTime(DateUtil.getNow());
                            insertRatioList.add(insertRatio);
                        }
                    } else {
                        if (dbRatio.getRatio() == null && e.getToBeEffectiveRatio() == null) {
                            deleteRatioList.add(dbRatio.getRatioId());
                        } else {
                            dbRatio.setUpdateTime(DateUtil.getNow());
                            dbRatio.setUpdater(mcStaff.getRealName());
                            dbRatio.setToBeEffectiveRatio(e.getToBeEffectiveRatio());
                            dbRatio.setEffectiveDate(effectiveDate);
                            updateRatioList.add(dbRatio);
                        }
                    }
                }
            }
        }

        if (CollectionUtil.isNotNullOrEmpty(insertRatioList)) {
            baseCityRatioService.insertBatch(insertRatioList);
        }
        if (CollectionUtil.isNotNullOrEmpty(deleteRatioList)) {
            baseCityRatioService.deleteByKeys(deleteRatioList);
        }
        if (CollectionUtil.isNotNullOrEmpty(updateRatioList)) {
            baseCityRatioService.updateToBeEffectiveRatioBatch(updateRatioList);
        }

    }

    @SuppressWarnings("Duplicates")
    private BaseCityRatio findBaseCityRatioByQueryOfCategOneRatioList(CityCategRatioQuery cityCategRatioQuery, List<BaseCityRatio> categOneRatioList) {
        BaseCityRatio baseCityPriceRatio;
        for (int i = 0; i < categOneRatioList.size(); i++) {
            baseCityPriceRatio = categOneRatioList.get(i);
            if (Objects.equals(cityCategRatioQuery.getCityId(), baseCityPriceRatio.getCityId()) && Objects.equals(cityCategRatioQuery.getServCategId(), baseCityPriceRatio.getServCategId())
                    && Objects.equals(cityCategRatioQuery.getCategOneId(), baseCityPriceRatio.getCategOneId()) && Objects.equals(cityCategRatioQuery.getBizType(), baseCityPriceRatio.getBizType())
                    && Objects.equals(cityCategRatioQuery.getPriceType(), baseCityPriceRatio.getPriceType()) && Objects.equals(cityCategRatioQuery.getRatioType(), baseCityPriceRatio.getRatioType())) {
                return baseCityPriceRatio;
            }
        }
        return null;
    }

    @SuppressWarnings("Duplicates")
    private BaseCityRatio findBaseCityRatioByQueryOfCategTwoRatioList(CityCategRatioQuery cityCategRatioQuery, List<BaseCityRatio> categTwoRatioList) {
        BaseCityRatio baseCityPriceRatio;
        for (int i = 0; i < categTwoRatioList.size(); i++) {
            baseCityPriceRatio = categTwoRatioList.get(i);
            if (Objects.equals(cityCategRatioQuery.getCityId(), baseCityPriceRatio.getCityId()) && Objects.equals(cityCategRatioQuery.getServCategId(), baseCityPriceRatio.getServCategId())
                    && Objects.equals(cityCategRatioQuery.getCategOneId(), baseCityPriceRatio.getCategOneId()) && Objects.equals(cityCategRatioQuery.getCategId(), baseCityPriceRatio.getCategId())
                    && Objects.equals(cityCategRatioQuery.getBizType(), baseCityPriceRatio.getBizType()) && Objects.equals(cityCategRatioQuery.getPriceType(), baseCityPriceRatio.getPriceType())
                    && Objects.equals(cityCategRatioQuery.getRatioType(), baseCityPriceRatio.getRatioType())) {
                return baseCityPriceRatio;
            }
        }
        return null;
    }
}
